#ifndef DW_BASE_FLOAT4_H
#	define DW_BASE_FLOAT4_H

#include <xmmintrin.h>
#include <emmintrin.h>

namespace dw {

dwAlignPre16 struct float4
{
public : //! @name Types definitions
	//! @{
	typedef float4 const& float4In;
	typedef float4& float4InOut;
	typedef float4 float4Return;
	//! @}

public : //! @name Constants
	//! @{
	static const float4 zero;
	static const float4 ones;
	//! @}

public : //! @name Construction & Destruction
	//! @{
	float4();
	float4(const float32 pX, const float32 pY, const float32 pZ, const float32 pW);
	float4(float4In ref);
	explicit float4(const __m128& ref);
	//! @}

public : //! @name Setup
	//! @{
	void set(const float32 pAll);
	void set(const float32 pX, const float32 pY, const float32 pZ, const float32 pW);
	void set(float4In ref);
	//! @}

public : //! @name State
	//! @{
	float32 length();
	float32 sqrLength();
	//! @}

public : //! @name Operations
	//! @{
	static float4Return add(const float4& lhs, const float4& rhs);
	static float4Return sub(const float4& lhs, const float4& rhs);
	static float4Return mul(const float4& lhs, const float4& rhs);
	static float4Return mad(const float4& lhs, const float4& rhs);

	static float dot(float4In lhs, float4In rhs);
	static float4Return normalize(float4In v);
	//! @}

public : //! @name Data
	//! @{
	__m128 m128;
	struct
	{
		float r, g, b, a;
	};
	struct
	{
		float x, y, z, w;
	};
	//! @}
} dwAlignPost16;

static float4 operator - (const float4& rhs);
static float4 operator + (const float4& lhs, const float4& rhs);
static float4 operator - (const float4& lhs, const float4& rhs);
static float4 operator * (const float4& lhs, const float4& rhs);

static float4 operator * (const float32& lhs, const float4& rhs);

} // namespace dw

#endif // !DW_BASE_FLOAT4_H
